package Util;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.usermodel.*;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 模板导出
 */
public class ExamineTemplateExportUtil {

    public TemplateInfo exportData(TemplateInfo templateInfo) {
        XSSFWorkbook xssfWorkbook = null;
        OutputStream out = null;
        List<Map<String,Object>> list = templateInfo.getDatas();
        int size = list.size();
        OPCPackage opcPackage = null;
        try {
            opcPackage = OPCPackage.open(templateInfo.getFile());
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        }
        try {
            if (templateInfo.getXssfWorkbook() == null) {
                xssfWorkbook = new XSSFWorkbook(opcPackage);
                templateInfo.setXssfWorkbook(xssfWorkbook);
            } else {
                xssfWorkbook = templateInfo.getXssfWorkbook();
            }

            XSSFSheet sheetAt;
            //获取第一次写入时单元格样式
            templateInfo.setCellStyles(getCellStyles(xssfWorkbook, templateInfo.getFirstWriteRow(), templateInfo.getDataName().length));
            if (templateInfo.getWriteSheet() == 0) {
                sheetAt = xssfWorkbook.getSheetAt(templateInfo.getWriteSheet());
                //获取第一次写入时单元格高度
                templateInfo.setRowHeight(getRowHeight(xssfWorkbook, templateInfo.getWriteRow()));
                templateInfo.setColumnWidth(getColumnWidth(xssfWorkbook, templateInfo.getDataName().length));
            } else {
                sheetAt = xssfWorkbook.createSheet("sheet" + templateInfo.getWriteSheet());
                templateInfo.setWriteRow(0);
                for (int r = 0; r < templateInfo.getDataName().length; r++) {
                    sheetAt.setColumnWidth(r, templateInfo.getColumnWidth().get(r));
                }
            }


            XSSFRow row;
            XSSFCell cell;
            Map<String,Object> o;
            Object fieldValueByName;
            int length = templateInfo.getDataName().length;
            for (int r = 0; r < size; r++) {
                row = sheetAt.createRow(r + templateInfo.getWriteRow());
                o = list.get(r);
                for (int c = 0; c < length; c++) {
                    cell = row.createCell(c);
                    cell.setCellStyle(templateInfo.getCellStyles().get(c));
                    //fieldValueByName = getFieldValueByName(templateInfo.getDataName()[c], o);
                    fieldValueByName = o.get(templateInfo.getDataName()[c]);
                    cell.setCellValue(fieldValueByName == null ? "" : fieldValueByName.toString());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return templateInfo;
    }

    /**
     * 获取单元格样式
     *
     * @param wb       文档
     * @param writeRow 获取的行标
     * @param size     行地址
     * @return 样式
     */
    private List<XSSFCellStyle> getCellStyles(XSSFWorkbook wb, int writeRow, int size) {
        XSSFRow row = wb.getSheetAt(0).getRow(writeRow);
        List<XSSFCellStyle> styles = new ArrayList<XSSFCellStyle>();
        for (int i = 0; i < size; i++) {
            styles.add(row.getCell(i).getCellStyle());
        }
        return styles;
    }

    /**
     * 获取内容单元格高度
     *
     * @param wb       文档
     * @param writeRow 获取的行标
     * @return 高度
     */
    private short getRowHeight(XSSFWorkbook wb, int writeRow) {
        return wb.getSheetAt(0).getRow(writeRow).getHeight();
    }

    /**
     * 获取内容单元格高度
     *
     * @param wb 文档
     * @return 高度
     */
    private List<Integer> getColumnWidth(XSSFWorkbook wb, int cellSize) {
        List<Integer> columnWidths = new ArrayList<>();
        for (int i = 0; i < cellSize; i++) {
            columnWidths.add(wb.getSheetAt(0).getColumnWidth(1));
        }
        return columnWidths;
    }

    /**
     * 获取对应值
     *
     * @param fieldName 属性名称
     * @param o         对象
     * @return 结果
     */
    private Object getFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[]{});
            Object value = method.invoke(o, new Object[]{});
            return value;
        } catch (Exception e) {
            return null;
        }
    }
}
